package com.zzyl.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.zzyl.base.PageResponse;
import com.zzyl.base.ResponseResult;
import com.zzyl.constant.AccraditationRecordConstant;
import com.zzyl.constant.PendingTasksConstant;
import com.zzyl.dto.ElderDto;
import com.zzyl.dto.MemberElderDto;
import com.zzyl.dto.RetreatDto;
import com.zzyl.dto.RetreatReqDto;
import com.zzyl.entity.*;
import com.zzyl.exception.BaseException;
import com.zzyl.mapper.*;
import com.zzyl.service.AccraditationRecordService;
import com.zzyl.service.ActFlowCommService;
import com.zzyl.service.RetreatService;
import com.zzyl.utils.UserThreadLocal;
import com.zzyl.vo.RecordVo;
import com.zzyl.vo.retreat.ElderVo;
import com.zzyl.vo.retreat.TasVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Slf4j
@Service
public class RetreatServiceImpl implements RetreatService {

    @Autowired
    private RetreatMapper retreatMapper;
    @Autowired
    private ContractMapper contractMapper;
    @Autowired
    private ElderMapper elderMapper;
    @Autowired
    private ActFlowCommService actFlowCommService;
    @Autowired
    private AccraditationRecordService accraditationRecordService;
    @Autowired
    private RetreatBillMapper retreatBillMapper;

    //撤销退住
    @Transactional
    @Override
    public ResponseResult cancel(String retreatCode, String taskId) {
        Retreat retreat = retreatMapper.getRetreatByCode(retreatCode);
        if (retreat != null) {
            throw new BaseException("退住单不存在");
        }
        retreatMapper.updateRetreatByFlowStatus(retreat.getId(), retreat.getFlowStatus() - 1);

        retreatMapper.updateStatus(retreat.getId(), Retreat.Status.CLOSED.getCode());

        if (retreat.getStatus() > 2) {
            contractMapper.updateByElderId(retreat.getElderId(), 1);
        }
        Elder elder = new Elder();
        elder.setId(retreat.getElderId());
        elder.setStatus(1);
        elderMapper.updateByPrimaryKeySelective(elder);
        actFlowCommService.closeProcess(taskId, PendingTasksConstant.TASK_STATUS_CLOSED);

        String subject = UserThreadLocal.getSubject();
        User user = JSON.parseObject(subject, User.class);

        RecordVo recordVo = getRecordVo(retreat, user,
                AccraditationRecordConstant.AUDIT_STATUS_DISAPPROVE, "",
                "撤销申请-申请退住", "",
                null,
                AccraditationRecordConstant.RECORD_HANDLE_TYPE_PROCESSED
        );
        accraditationRecordService.insert(recordVo);
        return ResponseResult.success();
    }

    /**
     * 驳回
     * @param retreatCode 退住申请编号
     * @param taskId 任务编号
     * @param message 驳回原因
     * @return 响应结果
     */
    @Override
    @Transactional
    public ResponseResult reject(String message, String retreatCode, String taskId) {
        String subject = UserThreadLocal.getSubject();
        User user = JSON.parseObject(subject, User.class);

        //查询退住单
        Retreat retreat = retreatMapper.getRetreatByCode(retreatCode);
        if (retreat == null) {
            throw new BaseException("退住单不存在");
        }

        //删除账单数据
        retreatBillMapper.deleteByByRetreatId(retreat.getId());

        //修改退住状态为0
        retreatMapper.updateRetreatByFlowStatus(retreat.getId(), Retreat.FlowStatus.APPLY.getCode());

        //如果审核状态大于3，则需要恢复老人合同为生效
        if (retreat.getFlowStatus() > 3) {
            contractMapper.updateByElderId(retreat.getElderId(), 1);
        }

        actFlowCommService.rollBackTask(taskId, true);

        //保存审核记录
        RecordVo recoreVo = getRecordVo(retreat, user,
                AccraditationRecordConstant.AUDIT_STATUS_DISAPPROVE, message,
                "驳回申请-", "",
                null, AccraditationRecordConstant.RECORD_HANDLE_TYPE_AUDIT);
        accraditationRecordService.insert(recoreVo);

        return ResponseResult.success();
    }

    /**
     * 退住管理
     *
     * @param reqDto 请求参数
     * @return 退住列表
     */
    @Override
    public ResponseResult selectByPage(RetreatReqDto reqDto) {
        PageHelper.startPage(reqDto.getPageNum(), reqDto.getPageSize());
        Page<List<Retreat>> pages = retreatMapper.selectByPage(reqDto);
        PageResponse<Retreat> of = PageResponse.of(pages, Retreat.class);
        return ResponseResult.success(of);
    }
    @Autowired
    private CheckInMapper checkInMapper;
    /**
     * 退住表单查询
     *
     * @param flowStatus  流程状态（0:申请退住，1:申请审批，2:解除合同，3:调整账单，4:账单审批，5:退住审批，6:费用算清）
     * @param retreatCode 退住编号
     * @param taskId      任务ID
     * @param assigneeId  当前处理人ID
     * @return 退住表单
     */
    @Override
    public ResponseResult<TasVo> getRetreat(Integer flowStatus, String retreatCode, String taskId, String assigneeId) {
        //查询退住表
        Retreat retreat = retreatMapper.selectByCode(retreatCode);
//        //查询checkIn
//        CheckIn checkIn = checkInMapper.(retreat.getId());
//        String otherApplyInfoAll = checkIn.getOtherApplyInfo();
//        JSONObject jsonObjectAll = JSON.parseObject(otherApplyInfoAll, JSONObject.class);
//        if (ObjectUtil.isNotEmpty(jsonObjectAll)) {
//            //获取老人的其他信息
//            String otherApplyInfo = jsonObjectAll.getString("otherApplyInfo");
//            checkInVo.setOtherApplyInfo(otherApplyInfo);
//
//            //获取老人家属信息
//            String memberElderDtosJsonStr = jsonObjectAll.getString("memberElderDtos");
//            List<MemberElderDto> memberElderDtoList = JSON.parseArray(memberElderDtosJsonStr, MemberElderDto.class);
//            checkInVo.setMemberElderDtos(memberElderDtoList);
//
//            //获取老人信息
//            String elderDtoJsonStr = jsonObjectAll.getString("elderDto");
//            ElderDto elderDto = JSON.parseObject(elderDtoJsonStr, ElderDto.class);
//            checkInVo.setElderDto(elderDto);
//
//            //老人的照片和身份证照片
//            checkInVo.setUrl1(jsonObjectAll.getString("url1"));
//            checkInVo.setUrl2(jsonObjectAll.getString("url2"));
//            checkInVo.setUrl3(jsonObjectAll.getString("url3"));
//        }
        /*
        isShow: 0:只展示操作记录  1:展示详细数据和操作记录
         */
        Integer isShow = 1;
        //前端传过来的flowStatus默认为-1,因为他也不知道当前走到了哪一步,所以需要我们做一个判断
        //判断当前登录人是否是该任务的执行人,如果是,则返回1
        //如果不是执行人,则返回0
        // flowStatus 0 1 2 3 4    -1
        if (flowStatus < 0) {
            flowStatus = retreat.getFlowStatus();
        }
        if (ObjectUtil.isNotEmpty(taskId)) {
            /*
            taskId: 任务id
            flowStatus: 用户点击的流程节点
            dbFlowStatus: 目前数据库里真实的流程状态
             */
            isShow = actFlowCommService.isCurrentUserAndStep(taskId, flowStatus, retreat.getFlowStatus());
        }

        Boolean isRevocation = false;
        if (isShow == 2 && retreat.getStatus().equals(CheckIn.Status.APPLICATION.getCode())) {
            isRevocation = true;
        }
        if (isShow == 2) {
            isShow = 1;
        }

        //查询操作记录表
        List<AccraditationRecord> recordList = accraditationRecordService.getAccraditationRecordByBuisId(retreat.getId(), AccraditationRecordConstant.RECORD_TYPE_RETREAT);
        TasVo tasVo = new TasVo();
        tasVo.setRetreat(retreat);
        tasVo.setAccraditationRecords(recordList);
        //退住
        tasVo.setType(AccraditationRecordConstant.RECORD_TYPE_CHECK_IN);
        tasVo.setIsShow(isShow);
        //判断是否显示撤回按钮
        tasVo.setIsRevocation(isRevocation);

        return ResponseResult.success(tasVo);
    }
    /**
     * 提交退住申请审批
     * @param retreatDto 退住申请审批
     * @return 响应结果
     */
    @Override
    public ResponseResult submitRetreat(RetreatDto retreatDto) {
        //从当前线程中获取用户数据
        String subject = UserThreadLocal.getSubject();
        User user = JSON.parseObject(subject, User.class);

        //判断当前操作人与登陆人是否一致
        if(ObjectUtil.isEmpty(retreatDto.getAssigneeId())
                ||!retreatDto.getAssigneeId().equals(user.getId().toString())){
            throw  new BaseException("当前操作人与登陆人不一致");
        }

        //查询退住数据
        Retreat retreat = retreatMapper.selectByCode(retreatDto.getCode());

        //判断老人是否已经完成了退住
        if(retreat.getStatus().equals(CheckIn.Status.FINISHED.getCode())){
            throw  new BaseException("老人已经完成了退住");
        }

        //准备操作记录对象
        RecordVo recordVo = new RecordVo();
        recordVo.setRealName(user.getRealName());
        recordVo.setUserId(user.getId());
        recordVo.setStatus(AccraditationRecordConstant.AUDIT_STATUS_PASS);
        recordVo.setId(retreat.getId());
        recordVo.setType(AccraditationRecordConstant.RECORD_TYPE_RETREAT);
        recordVo.setFlowStatus(retreat.getFlowStatus());

        //审核状态为1 ，护理主管审批
        if(recordVo.getStatus().equals(AccraditationRecordConstant.AUDIT_STATUS_PASS) ){
            //更新退住单状态
            retreatMapper.updateRetreatByFlowStatus(retreat.getId(), Retreat.FlowStatus.RESCISSION_CONTRACT.getCode());
            //操作记录
            recordVo.setOption("同意");
            recordVo.setStep("护理组长审批-申请审批");
            recordVo.setNextStep("法务处理-解除合同");
            recordVo.setHandleType(AccraditationRecordConstant.RECORD_HANDLE_TYPE_AUDIT);
        }

        return ResponseResult.success();
    }
    private RecordVo getRecordVo(Retreat retreat, User user, Integer status, String option, String step, String nextStep, Long nextAssigneeId, Integer handleType) {
        RecordVo recordVo = new RecordVo();
        recordVo.setId(retreat.getId());
        recordVo.setType(AccraditationRecordConstant.RECORD_TYPE_CHECK_IN);
        recordVo.setFlowStatus(retreat.getFlowStatus());
        recordVo.setHandleType(handleType);
        recordVo.setStatus(status);
        recordVo.setOption(option);
        recordVo.setStep(step);
        recordVo.setNextStep(nextStep);
        recordVo.setRealName(user.getRealName());
        recordVo.setUserId(user.getId());
        recordVo.setNextAssignee(nextAssigneeId);
        return recordVo;
    }
}
